DispatcherServlet 源码阅读(1)
有时间还是应该多看看源码。
DispatcherServlet 是一个实实在在的 Servlet,所以 Spring MVC 引入后不会改变 Servlet 容器的行为,仍然是解析 web.xml 部署文件,只需要在里面配置这个 Servlet 即可。
比如下面配置 dispatcher Servlet 处理所有的请求,也体现了 DispatcherServlet 是前端控制器(Front Controller)。contextConfigLocation 上下文参数用于配置路径的指定,如果没有的话就使用默认的值。
1 | <?xml version="1.0" encoding="UTF-8"?> |
DispatcherServlet 初始化
DispatcherServlet 的父类 HttpServletBean 覆盖了 HttpServlet 的 init 方法,实现该 servlet 的初始化。
1 | /** |
正如注释所说 initServletBean() 留由子类实现,体现了模板方法模式,当上述bean属性设置完成后,进入这里 FrameworkServlet#init() 创建 Servlet 的上下文 WebApplicationContext,initWebApplicationContext 首先会获得该 Web 应用的 root WebApplicationContext (通常是由 org.springframework.web.context.ContextLoaderListener 加载的),然后根据这个根上下文得到我们这个 Servlet 的 WebApplicationContext。initFrameworkServlet 方法是空的,而且子类 DispatcherServlet 也没有覆盖。
1 | /** |
DispatcherServlet 处理请求流程
FrameworkServlet 中覆盖了 HttpServlet 的 doGet(),doPost()等方法,而 doGet(),doPost()等又直接调用方法 processRequest 来处理请求,代码如下。
1 | /** |
然后我们进入 processRequest 方法,实际的请求处理是调用其抽象方法 doService。
1 | /** |
然后在 DispatcherServlet 中具体实现请求的处理分发,先是把一些资源放到请求属性中,然后调用 doDispatch 实现请求分发到控制器的 handler。doDispatch 中首先会判断是否是文件传输流的请求(利用MultipartResolver),如果是的话就会转为 MultipartHttpServletRequest。接下来 getHandler(processedRequest) 根据请求获得对应的handler,最后调用 handle() 处理请求,会反射到在控制器中实现的方法。
1 | /** |
HandlerAdapter接口的handle方法抽象的是一个handler如何处理一个请求,该接口实现有下面几个。
AnnotationMethodHandlerAdapter 基于HTTP请求的路径,方法,请求参数,使用 RequestMapping 注解来映handler,从 Spring 3.2建议使用RequestMappingHandlerAdapter。这里看看AnnotationMethodHandlerAdapter是如何实现handle方法的, 使用了反射,最后通过 invokeHandlerMethod 执行了对应的handler方法。
1 |
|
小结
不要满足于得心应手的事,要不断的做触及能力之上的东西,才会成长。